package org.vdab.projects.tasks.client.entities;

import org.vdab.projects.tasks.client.dal.GWTEntityManager;
import org.vdab.projects.tasks.client.util.ICommand;
import org.vdab.projects.tasks.client.util.MessageGuard;
import org.vdab.projects.tasks.shared.entities.IBaseEntity;
import org.vdab.projects.tasks.shared.entities.impl.BaseEntity;

import com.google.gwt.user.client.rpc.AsyncCallback;
/***
 * 
 * @author stijn
 *
 * @param <E> The type of the entity it represent. 
 * 
 * A clientEntiy represents a entity on client side. The clientEntity can contain the actual object, but does not 
 * necessarily, it will load the actual object only when first needed.   
 */
public abstract class ClientEntity<E extends BaseEntity<E>> implements IBaseEntity<E> {
		
	private E serverSideObject;
	
	private GWTEntityManager em;
	
	private String ssoKey;
	
	protected ClientEntity(String key, GWTEntityManager gwtEntityManager){
		this.em = gwtEntityManager;
		this.ssoKey = key;
	}

	protected ClientEntity(E sso,GWTEntityManager gwtEntityManager ){
		this(sso.getKey(),gwtEntityManager);		
		this.serverSideObject = sso;
		
		MessageGuard.Log("Created clientEntity " + this.getDisplayText());
	}
	
	public String getKey(){
		return ssoKey;
	}
	
	public void execute(final ICommand<E> command) throws Exception{
		if(isLoaded()){
			command.execute(this.serverSideObject);
		}else{
			load(ssoKey, new AsyncCallback<E>() {

				@Override
				public void onFailure(Throwable caught) {
					MessageGuard.Log("Faild when Loading. " + caught.getLocalizedMessage());
				}

				@Override
				public void onSuccess(E result) {
					MessageGuard.Log(result.getDisplayText()+ " loaded.");
					serverSideObject = result;					
					try {
						command.execute(result);
					} catch (Exception e) {
						MessageGuard.Log(e.getLocalizedMessage());
					}
				}			
			});		
		}			
	}     
	
	protected abstract void load(String key, AsyncCallback<E> onLoaded);
	
//	protected ClientEntityManager getEm(){
//		return this.em;
//	}
		
	protected Boolean isLoaded(){
		return this.serverSideObject != null;		
	}
	
	public String getDisplayText(){
		if(serverSideObject==null){
			return this.getClass().getName() + "(" + ssoKey + ")";
		}else{
			return "CE:" + this.serverSideObject.getDisplayText();
		}
	}
	
	public GWTEntityManager getManager(){
		return em;
	}
}
